#include <SoftwareSerial.h>

SoftwareSerial softserial(6, 5);
#define RxLCD 6
#define TxLCD 5
#define ledPin 13                // choose the pin for the LED
#define KeyOK 8
#define KeyESC 9
#define EncCHA 2                // choose the input pin (for a pushbutton)
#define EncCHB 3                // choose the input pin (for a pushbutton)
int EncValue = 0;
int EncPulse = 3;             //0 = Nothing, 1= Forward, 2= reverse, 3= redraw
int EncDivider = 10;
int EncDividerCountUP = 0;
int EncDividerCountDW = 0;
int TopScreen =0;
int OldTopScreen=0;
int MenuIndex=1;
int DMXchannel=1;
int FixtureNO=1;
int SceneNO=1;

const char* Menu1[] = {" 1.DMX Channel      ", 
                 " 2.Fixture          ", 
                 " 3.Scene            ",
                 " 4.Step             ",
                 " 5.Setup            ", 
                 ""};
const char* Menu2[] = {" 2.1MENU ORDINARIE  ", 
                 " 2.2BLABZABLE       ", 
                 " 2.3DERNIER         ",
                 ""};
const char* Menu3[] = {" 3.1Petit Menu      ", 
                 " 3.2Fixture         ", 
                 ""};

// String for drawing left arrow position, First line to last line
const char Position1[] = {0x80,0x7E,0x94,0x20,0xA8,0x20,0xBC,0x20,0};
const char Position2[] = {0x80,0x20,0x94,0x7E,0xA8,0x20,0xBC,0x20,0};
const char Position3[] = {0x80,0x20,0x94,0x20,0xA8,0x7E,0xBC,0x20,0};
const char Position4[] = {0x80,0x20,0x94,0x20,0xA8,0x20,0xBC,0x7E,0};

int Choix;
int TapAvg[10];
int ReadTimeTap;
int TapSyncTime;
int LastTapSyncTime;

int pinto=0;


// Interrupt of the rotary encoder wheel
// It is call only on the rising edge of one of the 
// two quadrature channel.
void Rotary()
{
  if (digitalRead(EncCHB))
  { 
    // Up Direction High Speed  
    if (EncDividerCountUP++ > EncDivider)
    {
      EncDividerCountUP=0;
      EncPulse =1;
    }
  }
  else 
  {
    // Down direction  
    if (EncDividerCountDW++ > EncDivider)
    {
      EncDividerCountDW = 0;  
      EncPulse =2;
    }        
  }
}


// For later use.
void TapSync()
{
  ReadTimeTap = millis();
  //digitalWrite(ledPin,1-digitalRead(ledPin));
  TapSyncTime = ReadTimeTap-LastTapSyncTime;
  LastTapSyncTime = ReadTimeTap;
}



void setup()
{
  //Config of the rotary encoder
  pinMode(EncCHA, INPUT);
  pinMode(EncCHB, INPUT);
  pinMode(1, OUTPUT);
  pinMode(ledPin, OUTPUT);      // declare LED as output
  pinMode(TxLCD, OUTPUT);
  pinMode(KeyOK, INPUT);
  pinMode(KeyESC, INPUT);
  digitalWrite(KeyOK, HIGH); // Turn ON the pull up resistor
  digitalWrite(KeyESC, HIGH);

  digitalWrite(TxLCD, HIGH);
  delay (100);
  softserial.begin(9600);
  Serial.begin(9600);
  delay (100);
  softserial.print(22, BYTE); // turn on LCD, No Cursor
  softserial.print(17, BYTE); // turn on back light
  delay (50);
  softserial.print(12, BYTE); // Clear Screen
  softserial.print(" DMX Console V1.0");
  softserial.print(0x0D, BYTE);
  softserial.print(" Press (ESC)");
  while (digitalRead(KeyESC));
  softserial.print(12, BYTE); // Clear Screen
  while (!digitalRead(KeyESC));

interrupts();
attachInterrupt(0,Rotary,RISING);
//attachInterrupt(1,TapSync,RISING);
}


// To print a fix value in lenght
void PrintFixValue(int Data, int Fix)
{
  noInterrupts();
  if (Fix > 1) {
    if (Data < 10)
      softserial.print("0");
  } 
  if (Fix > 2) {
    if (Data < 100)
      softserial.print("0");
  } 
  if (Fix > 3 ) {
    if (Data < 1000)
      softserial.print("0");
  } 
  if (Fix > 4  ) {
    if (Data < 10000)
      softserial.print("0");
  } 
  softserial.print(Data);
  interrupts();
}


// To Enter a Value with the rotary wheel
int EnterValue(const char *Text, int Donnee, int Range)
{
  int OldEncDivider = EncDivider;
  EncDivider = 1;
  noInterrupts();
  softserial.print(12, BYTE); // Clear Screen
  softserial.print(Text);
  softserial.print(0x0D, BYTE);
  softserial.print("Current Value :");
  PrintFixValue(Donnee,3);
  softserial.print(0x0D, BYTE);
  softserial.print("Range : (0-");
  softserial.print(Range);
  softserial.print(")");
  softserial.print(0x0D, BYTE);
  softserial.print("New Value :");
  softserial.print(0xC7, BYTE);
  PrintFixValue(Donnee,3);

  do {
    interrupts();
    if (EncPulse ==1) {
      if (++Donnee>Range)
        Donnee=Range;
    }
    if (EncPulse ==2) {
      if (Donnee)
        Donnee--;
    }
    if (EncPulse) {
      noInterrupts();
      softserial.print(0xC7, BYTE);
      PrintFixValue(Donnee, 3);
      EncPulse=0;
    }
  interrupts();
  }
  while (digitalRead(KeyESC) && digitalRead(KeyOK));
  EncDivider = OldEncDivider;
  if (digitalRead(KeyESC))
    return (Donnee);
  else 
    return (-1);
}


// Menu function
// Move the arrow and return the new position the choice
int ScrollMenu(const char *Menu[], int Direction)
{
  int i,j;
  if (Direction == 1)
  { 
    if (Menu[EncValue+1][0])
    {
      if (++EncValue>3)
      {  
        EncValue=3;
        if (Menu[TopScreen+EncValue+1][0])
        {
          TopScreen++;
        }
      }
    }  
  }
  else if (Direction ==2 )
  {
    if (EncValue)
    {
      EncValue--;  
    }
    else
    {
      if (TopScreen)
        TopScreen--;
    }
  }
  noInterrupts();
  if (OldTopScreen != TopScreen || Direction == 3)
  {
    OldTopScreen = TopScreen;
    softserial.print(0x80, BYTE);
    j=0;
    for (i = TopScreen;j<4 && Menu[i];i++)
    {
      j++;
      if (Menu[i])
        softserial.print(Menu[i]);
        Serial.print(Menu[i]);
    }
  }
  if (EncValue == 0)
  {
    softserial.print(Position1);
  }
  if (EncValue == 1)
  {
    softserial.print(Position2);
  }
  if (EncValue == 2)
  {
    softserial.print(Position3);
 }
  if (EncValue == 3)
  {
    softserial.print(Position4);
  }
  interrupts();
  
  return (TopScreen+EncValue);
}


void ResetMenu()
{
  MenuIndex =1;
  EncPulse =3;
  EncValue=0;
  TopScreen =0;
}

void loop()
{
  int temp;
  digitalWrite(ledPin,1-digitalRead(KeyOK));
  if (EncPulse)
  {
    if (MenuIndex ==1)
    {
      Choix=ScrollMenu(Menu1, EncPulse);
      EncPulse=0;
    }
    else if (MenuIndex ==11)
    {
      temp = EnterValue("Fixture", FixtureNO, 127);
      if (temp != -1)
        FixtureNO = temp;
      EncPulse=0;
    }
    else if (MenuIndex ==10)
    {
      temp = EnterValue("DMX Channel", DMXchannel, 512);
      if (temp != -1)
        DMXchannel = temp;
      EncPulse=0;
    }
    else if (MenuIndex ==12)
    {
      temp = EnterValue("Scene No.", SceneNO,127);
      if (temp != -1)
        SceneNO = temp;
      EncPulse=0;
    }
    else if (MenuIndex ==13)
    {
      Choix=ScrollMenu(Menu2, EncPulse);
      EncPulse=0;
    }
    else ResetMenu();
 
  }
  if (!digitalRead(KeyOK))
  {
    MenuIndex = MenuIndex*10 + Choix;
    if (MenuIndex > 10000 || MenuIndex < 1)
      ResetMenu();
    EncPulse = 3;
    EncValue=0;
    TopScreen =0;
    softserial.print(12, BYTE); // Clear Screen
    delay(50); 
    while (!digitalRead(KeyOK));
  }
  if (!digitalRead(KeyESC) && MenuIndex != 1)
  {
    MenuIndex = MenuIndex/10;
    if (MenuIndex<1)
      ResetMenu;
    EncPulse = 3;
    EncValue=0;
    TopScreen =0;
    softserial.print(12, BYTE); // Clear Screen
    delay(50); 
    while (!digitalRead(KeyESC));
  }

} 
